package com.tools.db.jdbc;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.tools.common.container.*;
import com.tools.common.exception.SQLRuntimeException;
import com.tools.common.io.ProfileKit;
import com.tools.common.object.*;
import com.tools.common.object.string.StrKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.lang.reflect.Array;
import java.sql.*;
import java.util.*;

/**
 * JDBC 操作工具类
 * 但在其中集成了 Druid
 * 连接池
 * */
@Note("JDBC 操作工具类，但在其中集成了 Druid 连接池")
public final class JdbcKit {

    private JdbcKit() {}

    @Note("默认的 Druid 数据源，但并未初始化，待需要使用时懒加载")
    private static volatile DruidDataSource DATASOURCE;

    @Note("日志输出对象")
    private static final Logger LOGGER = LoggerFactory.getLogger(JdbcKit.class);

    /* *******************************************************************************************
     *
     *          构造数据源对象
     *
     * *******************************************************************************************
     * */

    @Note("扫描项目的配置文件，根据默认的连接池的已有配置，拷贝一个全新的 Druid 的连接池返回")
    public static DruidDataSource newDataSource() {
        private_lazyLoadDataSource();
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(DATASOURCE.getDriverClassName());
        dataSource.setUrl(DATASOURCE.getUrl());
        dataSource.setUsername(DATASOURCE.getUsername());
        dataSource.setPassword(DATASOURCE.getPassword());
        dataSource.setMaxWait(DATASOURCE.getMaxWait());
        dataSource.setEnable(true);
        dataSource.setMaxActive(DATASOURCE.getMaxActive());
        dataSource.setMinIdle(DATASOURCE.getMinIdle());
        dataSource.setInitialSize(DATASOURCE.getInitialSize());
        return dataSource;
    }


    @Note("根据入参的连接池的数据源配置对象构建一个 Druid 的连接池")
    public static DruidDataSource newDataSource(DBSource dbSource) {
        if(dbSource == null) throw new IllegalArgumentException("连接池数据源配置信息对象 DBSource 不能为 null");
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(dbSource.getDriverClass());
        dataSource.setUrl(dbSource.getUrl());
        dataSource.setUsername(dbSource.getUsername());
        dataSource.setPassword(dbSource.getPassword());
        dataSource.setMaxWait(dbSource.getMaxWait());
        dataSource.setDefaultAutoCommit(true);
        dataSource.setMaxActive(dbSource.getMaxActive());
        dataSource.setMinIdle(dbSource.getMinIdle());
        dataSource.setInitialSize(dbSource.getInitialSize());
        return dataSource;
    }

    /* *******************************************************************************************
     *
     *          连接对象
     *
     * *******************************************************************************************
     * */


    @Note("获取默认开启自动提交事务的 DruidPooledConnection 连接对象")
    public static DruidPooledConnection openConnection() {
        private_lazyLoadDataSource();
        try {
            DruidPooledConnection connection = DATASOURCE.getConnection();
            connection.setAutoCommit(true);
            return connection;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("获取 DruidPooledConnection 连接对象，并根据 autoCommit 来决定是否开启事务自动提交")
    public static DruidPooledConnection openConnection(boolean autoCommit) {
        private_lazyLoadDataSource();
        try {
            DruidPooledConnection connection = DATASOURCE.getConnection();
            connection.setAutoCommit(autoCommit);
            return connection;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("根据外部入参的 Druid 的数据源对象获取开启自动提交事务 Connection 连接对象")
    public static Connection openConnection(DataSource dataSource) {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("根据外部入参的 Druid 的数据源对象获取 Connection 连接对象，" +
            "并根据 autoCommit 来决定是否开启事务自动提交")
    public static Connection openConnection(DataSource dataSource, boolean autoCommit) {
        try {
            Connection connection = dataSource.getConnection();
            connection.setAutoCommit(autoCommit);
            return connection;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    /* ***********************************************************************************
     *
     *          SQL 执行对象
     *
     * **********************************************************************************
     * */


    @Note("从 Connection 连接对象中获取 Statement SQL 执行对象")
    public static Statement newStatement(Connection connection) {
        try {
            return connection.createStatement();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 Connection 连接对象获取 Statement SQL执行对象，并且根据 freeScroll 决定是否开启自由滚动结果集，默认是关闭状态")
    public static Statement newStatement(Connection connection, boolean freeScroll) {
        try {
            return freeScroll
                    ? connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
                    : connection.createStatement();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 Connection 连接对象获取 PreparedStatement 对象，并预编译 SQL。")
    public static PreparedStatement newPreparedStatement(Connection connection, String sql) {
        try {
            return connection.prepareStatement(sql);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 Connection 连接对象获取 PreparedStatement 对象对 SQL 进行预编译，并且根据 freeScroll 决定是否开启自由滚动结果集，默认是关闭状态")
    public static PreparedStatement newPreparedStatement(Connection connection, String sql, boolean freeScroll) {
        try {
            return freeScroll
                    ? connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
                    : connection.prepareStatement(sql);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 Connection 连接对象获取 PreparedStatement 对象，并预编译 SQL，然后设置对应的参数")
    public static PreparedStatement newPreparedStatement(Connection connection, String sql, Object... parameters) {
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatementFillParameters(preparedStatement, parameters);
            LOGGER.info("SQL: {}", private_getCompleteSQLString(preparedStatement));
            return preparedStatement;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 Connection 连接对象获取 PreparedStatement 对象，并预编译 SQL，然后设置对应的参数，" +
            "并且根据 freeScroll 决定是否开启自由滚动结果集，默认是关闭状态")
    public static PreparedStatement newPreparedStatement(Connection connection, String sql, boolean freeScroll, Object... parameters) {
        try {
            PreparedStatement preparedStatement = freeScroll
                    ? connection.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)
                    : connection.prepareStatement(sql);
            preparedStatementFillParameters(preparedStatement, parameters);
            LOGGER.info("SQL: {}", private_getCompleteSQLString(preparedStatement));
            return preparedStatement;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("为预编译的 SQL 填充预先位置上的参数")
    public static void preparedStatementFillParameters(PreparedStatement preparedStatement, Object... parameters) {
        if(parameters == null || parameters.length == 0) return;
        try {
            for (int i = 0; i < parameters.length; i++) {
                preparedStatement.setObject(i + 1, parameters[i]);
            }
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 ResultSet 结果集对象反向获取 Statement 对象")
    public static Statement getStatement(ResultSet resultSet) {
        try {
            return resultSet.getStatement();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    /* ***********************************************************************************
     *
     *         SQL 执行方法
     *
     * **********************************************************************************
     * */

    @Note("获取 SQL 执行的结果")
    public static boolean execute(Statement statement, String sql) {
        try {
            LOGGER.info("SQL: {}", sql);
            long start = System.currentTimeMillis();
            boolean result = statement.execute(sql);
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return result;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("获取查询 SQL 执行的结果")
    public static ResultSet executeQuery(Statement statement, String sql) {
        try {
            LOGGER.info("SQL: {}", sql);
            long start = System.currentTimeMillis();
            ResultSet resultSet = statement.executeQuery(sql);
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return resultSet;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 SQL 执行器执行更新 SQL，获取对应的更新条目数")
    public static int executeUpdate(Statement statement, String sql) {
        try {
            LOGGER.info("SQL: {}", sql);
            long start = System.currentTimeMillis();
            int result = statement.executeUpdate(sql);
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return result;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 SQL 执行器执行大批量更新 SQL，获取对应的更新条目数")
    public static long executeLargeUpdate(Statement statement, String sql) {
        try {
            LOGGER.info("SQL: {}", sql);
            long start = System.currentTimeMillis();
            long result = statement.executeLargeUpdate(sql);
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return result;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 PreparedStatement 执行预编译 + 参数的 SQL，最后获取 SQL 执行的结果")
    public static boolean execute(PreparedStatement statement) {
        try {
            long start = System.currentTimeMillis();
            boolean result = statement.execute();
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return result;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("使用 SQL 执行器执行 SQL，获取对应的结果集，SQL 执行器已提前预编译了 SQL 和进行了参数填充")
    public static ResultSet executeQuery(PreparedStatement statement) {
        try {
            long start = System.currentTimeMillis();
            ResultSet resultSet = statement.executeQuery();
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
            return resultSet;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    @Note("使用 SQL 执行器执行更新 SQL，获取对应的更新条目数，SQL 执行器已提前预编译了 SQL 和进行了参数填充")
    public static int executeUpdate(PreparedStatement statement) {
        int count;
        try {
            long start = System.currentTimeMillis();
            count = statement.executeUpdate();
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
        return count;
    }


    @Note("使用 SQL 执行器执行批量更新 SQL，获取对应的更新条目数，SQL 执行器已提前预编译了 SQL 和进行了参数填充")
    public static long executeLargeUpdate(PreparedStatement statement) {
        long count;
        try {
            long start = System.currentTimeMillis();
            count = statement.executeLargeUpdate();
            long end = System.currentTimeMillis();
            LOGGER.info("ExecTime: {} ms", end - start);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
        return count;
    }

    /* ***********************************************************************************
     *
     *         元数据获取方法
     *
     * **********************************************************************************
     * */


    @Note("根据 ResultSet 结果集对象获取其元数据对象")
    public static ResultSetMetaData getResultSetMetaData(ResultSet resultSet) {
        try {
            return resultSet.getMetaData();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("根据结果集元数据对象，获取结果集的列数，也就是多少个字段")
    public static int getResultColumnCount(ResultSetMetaData metaData) {
        try {
            return metaData.getColumnCount();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("获取索引对应列的名称")
    public static String getColumnNameByIndex(ResultSetMetaData metaData, int columnIndex) {
        try {
            return metaData.getColumnName(columnIndex);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    @Note("获取索引对应列的类型名称，这个类型是数据库的字段类型")
    public static String getColumnJdbcTypeName(ResultSetMetaData metaData, int columnIndex) {
        try {
            return metaData.getColumnTypeName(columnIndex);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    @Note("获取索引对应列的类型名称，这个类型是 Java 的类型全路径")
    public static String getColumnJavaTypeName(ResultSetMetaData metaData, int columnIndex) {
        try {
            return metaData.getColumnClassName(columnIndex);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("获取结果集的最大行数，前提是要开启结果集自由滚动，否则会抛异常")
    public static int resultSetMaxRow(ResultSet resultSet) {
        int rowNumber;
        try {
            resultSet.last();
            rowNumber = resultSet.getRow();
            resultSet.beforeFirst();
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
        return rowNumber;
    }

    /* ***********************************************************************************
     *
     *         结果集封装
     *
     * **********************************************************************************
     * */

    @Note("获取指定索引对应字段的字段值")
    public static Object getResultValueByColumnIndex(ResultSet resultSet, int columnIndex) {
        try {
            return resultSet.getObject(columnIndex);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    @Note("获取指定名称的字段的字段值")
    public static Object getResultValueByColumnName(ResultSet resultSet, String columnName) {
        try {
            return resultSet.getObject(columnName);
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }


    @Note("将单条记录转为目标类型的值返回")
    public static <T>T processOneResult(ResultSet resultSet, C<T> resultType) {
        try {
            return resultSet.next()
                    ? (T) private_toRealValue(resultSet, resultType)
                    : null;
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
    }

    @Note("将多条记录转为指定类型的 List 集合")
    public static <T> List<T> processMultipleResult(ResultSet resultSet, C<T> resultType) {
        ArrayList<T> results = new ArrayList<>();
        try {
            while (resultSet.next()) {
                T obj = (T) private_toRealValue(resultSet, resultType);
                results.add(obj);
            }
        } catch (SQLException e) {
            throw new SQLRuntimeException(e);
        }
        return results;
    }


    /* *******************************************************************************************
     *
     *          回收/关闭对象
     *
     * *******************************************************************************************
     * */

    @Note("关闭 DruidDataSource 数据源对象")
    public static void close(DruidDataSource dataSource) {
        if(dataSource != null) {
            dataSource.close();
        }
    }


    @Note("回收 Connection 连接对象")
    public static void close(Connection connection) {
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                throw new SQLRuntimeException(e);
            }
        }
    }


    @Note("关闭 Statement 执行器对象")
    public static void close(Statement statement) {
        if(statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                throw new SQLRuntimeException(e);
            }
        }
    }


    @Note("关闭 ResultSet 结果集对象")
    public static void close(ResultSet resultSet) {
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                throw new SQLRuntimeException(e);
            }
        }
    }

    @Note("仅关闭结果集对象和 SQL 执行器对象，因为连接对象可复用，他们俩不行")
    public static void close(ResultSet resultSet, Statement statement) {
        close(resultSet);
        close(statement);
    }


    @Note("仅关闭结果集对象、 SQL 执行器对象，然后回收连接对象")
    public static void close(ResultSet resultSet, Statement statement, Connection connection) {
        close(resultSet);
        close(statement);
        close(connection);
    }

    /* *******************************************************************************************
     *
     *          私有逻辑
     *
     * *******************************************************************************************
     * */

    @Note("获取设置了参数的、完整的 SQL 的字符串")
    private static String private_getCompleteSQLString(PreparedStatement statement) {
        return statement.toString().split(": ")[1];
    }

    @Note("懒加载默认的数据源")
    private static void private_lazyLoadDataSource() {
        if(DATASOURCE != null) return;
        synchronized (JdbcKit.class) {
            if(DATASOURCE != null) return;
            DBSource dbSource = ProfileKit.getDataBaseSource();
            DATASOURCE = newDataSource(dbSource);
        }
    }


    @Note("构建 Map 集合，然后将 ResultSet 单条记录的所有字段和值装载入 Map 集合里返回")
    private static Map private_buildMapByResultSet(C<?> mapType, ResultSet resultSet, ResultSetMetaData metaData, int columnCount) {
        Map result;
        if(mapType.hasGenericType()) {
            C<?> keyType = mapType.generic(0);
            if(keyType != null && !String.class.equals(keyType.getMainType())) {
                throw new ClassCastException("结果集转换为 Map 集合时，其 key 必须要是字符串，" +
                        "当前 key 的类型为: 【" + keyType.getMainType().getName() + "】");
            }
            result = MapEnum.buildMap(mapType, columnCount);
            C<?> valueType = mapType.generic(1);
            for (int i = 0; i < columnCount; i++) {
                int index = i + 1;
                String columnName = getColumnNameByIndex(metaData, index);
                Object o = getResultValueByColumnIndex(resultSet, index);
                Object realValue = ObjKit.toRealValue(o, valueType);
                result.put(StrKit.toProperty(columnName), realValue);
            }
            return result;
        }
        result = MapEnum.buildMap(mapType, columnCount);
        for (int i = 0; i < columnCount; i++) {
            int index = i + 1;
            String columnName = getColumnNameByIndex(metaData, index);
            Object o = getResultValueByColumnIndex(resultSet, index);
            result.put(StrKit.toProperty(columnName), o);
        }
        return result;
    }


    @Note("构建自定义键值对容器集合，然后将 ResultSet 单条记录的所有字段和值装载入自定义键值对容器集合里返回")
    private static OwnPairs private_buildPairByResultSet(C<?> pairType, ResultSet resultSet, ResultSetMetaData metaData, int columnCount) {
        OwnPairs result = MapEnum.buildPair(pairType, columnCount);
        if(pairType.hasGenericType()) {
            C<?> keyType = pairType.generic(0);
            if(keyType != null && !String.class.equals(keyType.getMainType())) {
                throw new ClassCastException("结果集转换为 Map 集合时，其 key 必须要是字符串，" +
                        "当前 key 的类型为: 【" + keyType.getMainType().getName() + "】");
            }
            C<?> valueType = pairType.generic(1);
            for (int i = 0; i < columnCount; i++) {
                String columnName = getColumnNameByIndex(metaData, i + 1);
                String name = StrKit.toProperty(columnName);
                Object o = getResultValueByColumnIndex(resultSet, i + 1);
                result.put(name, ObjKit.toRealValue(o, valueType));
            }
            return result;
        }
        for (int i = 0; i < columnCount; i++) {
            String columnName = getColumnNameByIndex(metaData, i + 1);
            Object o = getResultValueByColumnIndex(resultSet, i + 1);
            result.put(StrKit.toProperty(columnName), o);
        }
        return result;
    }


    @Note("构建数组，然后将 ResultSet 的所有值从左往右放入数组中")
    private static Object private_buildArrayByResultSet(C<?> componentType, ResultSet resultSet, int maxColumn) {
        Object result = Array.newInstance(componentType.getMainType(), maxColumn);
        for (int i = 0; i < maxColumn; i++) {
            Object o = getResultValueByColumnIndex(resultSet, i + 1);
            Object realValue = ObjKit.toRealValue(o, componentType);
            Array.set(result, i, realValue);
        }
        return result;
    }

    @Note("构建 Collection 集合，然后将 ResultSet 的所有值从左往右放入 Collection 集合中")
    private static Collection private_buildCollectionByResultSet(C<?> collectionType, ResultSet resultSet, int columnCount) {
        Class<?> mainType = collectionType.getMainType();
        Collection result;
        if(Set.class.isAssignableFrom(mainType)) {
            result = SetEnum.buildSet(collectionType, columnCount);
        } else {
            result = ListEnum.buildList(collectionType, columnCount);
        }
        if(collectionType.hasGenericType()) {
            C<?> componentType = collectionType.generic(0);
            for (int i = 0; i < columnCount; i++) {
                Object o = getResultValueByColumnIndex(resultSet, i + 1);
                result.add(ObjKit.toRealValue(o, componentType));
            }
            return result;
        }
        for (int i = 0; i < columnCount; i++) {
            Object o = getResultValueByColumnIndex(resultSet, i + 1);
            result.add(o);
        }
        return result;
    }


    @Note("构建自定义容器，然后将 ResultSet 的所有值从左往右放入自定义容器中")
    private static OwnRows private_buildOwnRowsByResultSet(C<?> bc, ResultSet resultSet, int maxColumn) {
        OwnRows result = RowKit.buildRow(bc, maxColumn);
        if(bc.hasGenericType()) {
            C<?> componentType = bc.generic(0);
            for (int i = 0; i < maxColumn; i++) {
                Object o = getResultValueByColumnIndex(resultSet, i + 1);
                Object realValue = ObjKit.toRealValue(o, componentType);
                result.add(realValue);
            }
            return result;
        }
        for (int i = 0; i < maxColumn; i++) {
            Object o = getResultValueByColumnIndex(resultSet, i + 1);
            result.add(o);
        }
        return result;
    }


    @Note("将 ResultSet 的数据封装为指定类型的值返回")
    private static Object private_toRealValue(ResultSet resultSet, C<?> resultType) {
        Class<?> objClass = resultType.getMainType();
        ResultSetMetaData metaData = getResultSetMetaData(resultSet);
        int columnCount = getResultColumnCount(metaData);
        try {
            if(columnCount == 0) {
                return BasicEnum.isBasic(objClass)
                        ? BasicEnum.getDefaultValue(objClass)
                        : null;
            }
            if(columnCount == 1) {
                Object value = resultSet.getObject(1);
                if(value == null) return null;
                //如果目标类型是基本类型
                Object newValue = BasicEnum.matchAndGetValue(value, objClass);
                if(newValue != null) {
                    return newValue;
                }
                //如果目标类型是字符串
                if(String.class.equals(objClass)) {
                    return value.toString();
                }
                //如果目标类型是日期类型
                if(DateKit.isDateClass(objClass)) {
                    return DateKit.toDateEntity(value, objClass, resultType.getDateFormatPattern());
                }
                //如果目标类型是枚举类型
                if(Enum.class.isAssignableFrom(objClass)) {
                    return Enum.valueOf((Class) objClass, value.toString());
                }
                String columnName = metaData.getColumnName(1);
                Object bean = ObjKit.buildObject(resultType, resultSet, metaData, columnCount);
                Object realValue = ObjKit.toRealValue(value, C.getC(value.getClass()));
                String property = StrKit.toProperty(columnName);
                ObjKit.setFieldValue(bean, property, realValue);
                return bean;
            }
            //列数不为 1，且目标类型是 Map
            if(Map.class.isAssignableFrom(objClass)) {
                return private_buildMapByResultSet(resultType, resultSet, metaData, columnCount);
            }
            //列数不为 1，且目标类型是自定义键值对
            if(OwnPairs.class.isAssignableFrom(objClass)) {
                return private_buildPairByResultSet(resultType, resultSet, metaData, columnCount);
            }
            //列数不为 1，如果是数组
            if(objClass.isArray()) {
                return private_buildArrayByResultSet(resultType, resultSet, columnCount);
            }
            //如果是集合
            if(Collection.class.isAssignableFrom(objClass)) {
                return private_buildCollectionByResultSet(resultType, resultSet, columnCount);
            }
            //如果是自定义容器
            if(OwnRows.class.isAssignableFrom(objClass)) {
                return private_buildOwnRowsByResultSet(resultType, resultSet, columnCount);
            }
            //最后才是 JavaBean 对象
            return ObjKit.buildObject(resultType, resultSet, metaData, columnCount);
        } catch (Exception e) {
            throw new SQLRuntimeException(e);
        }
    }
}
